/*******************************************************************************
  * 文件：DevRun.c
  * 作者：djy
  * 版本：v1.0.0
  * 日期：2024.09.11
  * 说明：设备运行-UI navigaiton
*******************************************************************************/
/* 头文件 *********************************************************************/
#include "DevRun.h"
#include "DevState.h"
#include "RunProtect.h"
#include "DevStandby.h"
#include "Debug.h"
#include "Buzzer.h"
#include "Hardware_IO.h"
#include "Display.h"
#include "HobCtrl.h"
#include "Debug.h"
#include "ComFun.h"
#include "YLDeviceCtrl.h"
#include "RunProtect.h"
#include "Relay.h"
#include "Fan.h"

/* 宏定义 *********************************************************************/
/* 类型定义 *******************************************************************/
/* 变量定义 *******************************************************************/
DevRunCtrl_ts sDevRunCtrl;
/* 函数声明 *******************************************************************/
/* 函数定义 *******************************************************************/

/*******************************************************************************
  * 函数名：DevRun_TimingTimeBlinkHook
  * 功  能：设备运行-定时时间闪烁回调函数
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
static void DevRun_TimingTimeBlinkHook(void)
{
    // 状态改变，提前退出
    if(eDEV_RUN != Dev_GetCurrentState())
    {
        OS_TimerStop(&sDevRunCtrl.sTimeBlinkTimer);
        return;
    }

    // 闪烁定时时间
    if(OS_TimerGetExpiredTimes(&sDevRunCtrl.sTimeBlinkTimer)%2)
    {
        // 根据选中炉头，显示时间
        Display_ShowTime(sDevRunCtrl.au8TimingTime[sDevRunCtrl.u8CZIndex]);

        // 闪烁时间到
        if(OS_TimerGetExpiredTimes(&sDevRunCtrl.sTimeBlinkTimer) == 7)
        {
            // 确认提示音
            Buzzer_Play(eBUZZER_SOUND_KEY_PRESS,eBUZZER_VOL_HIGH);

            // 若所有炉头均未开启定时，则直接清除时间显示
            if(DevRun_CheckTimingEnable() == FALSE)
            {
                // 取消CZ指向
                sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
                
                // 信息调试
                DEBUG("All CZs exit duration\r\n");
                
                // 显示--
                Display_ShowIdle();
                
                // 停止时间闪烁定时器
                OS_TimerStop(&sDevRunCtrl.sTimeBlinkTimer);
            }
            else
            {
                // 有炉头在定时，需要将索引指向定时时间最短的炉头
                U8 u8ShortestCZ = u8CZ_INVALID;
                U16 u16TimingTimeSec = u16MAX_VALUE;

                // 查找处于定时中且时长最小的CZ
                for(U8 u8CZIndex = u8CZ1;u8CZIndex <= u8CZ4;u8CZIndex++)
                {
                    if(sDevRunCtrl.bTimerEnable[u8CZIndex] == TRUE && sDevRunCtrl.au16TimingTimeS[u8CZIndex] < u16TimingTimeSec)
                    {
                        u8ShortestCZ = u8CZIndex;
                        u16TimingTimeSec = sDevRunCtrl.au16TimingTimeS[u8CZIndex];
                    }
                }

                // 信息调试
                DEBUG("Reset CZ:%d timer,Shortest CZ:%d\r\n",sDevRunCtrl.u8CZIndex+1,u8ShortestCZ+1);

                // 根据当前选中炉头，重启运行定时器
                OS_TimerReset(&sDevRunCtrl.asLevelBlinkTimer[sDevRunCtrl.u8CZIndex]);

                // 将当前指向的CZ重新指向u8ShortestCZ
                sDevRunCtrl.u8CZIndex = u8ShortestCZ;
                
                // 启动运行时间管理
                OS_TimerRestart(&sDevRunCtrl.sTimeBlinkTimer,500,HobCtrl_DurationTimingHook);
            }
        }
    }
    else
    {
        // 清除时间显示
        Display_ClearTime();
    }

}

/*******************************************************************************
  * 函数名：DevRun_CZ1LevelBlinkHook
  * 功  能：设备运行-CZ1档位闪烁回调函数
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void DevRun_CZ1LevelBlinkHook(void)
{
    // 状态改变提前退出
    if(eDEV_RUN != Dev_GetCurrentState())
    {
        OS_TimerStop(&sDevRunCtrl.asLevelBlinkTimer[u8CZ1]);
        return;
    }

    // 根据当前状态，执行闪烁规则
    switch(sDevRunCtrl.eRunState[u8CZ1])
    {
    case eHOB_IDLE_S1:
        // 检查是否需要高温提醒
        if(YLComm_CoilTempGet(u8CZ1) > U8_COIL_OVERHEAT_TEMPER)
        {
            // 闪烁‘H’
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ1])%2)
            {
                // 显示'H'
                Display_Hob1Hot();

                // 信息调试
                DEBUG("CZ1 is hot\r\n");
            }
            else
            {
                // 清除显示
                Display_Hob1Clear();
            }
        }
        else
        {
            // 闪烁档位
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ1])%2)
            {
                // 显示档位
                Display_Hob1Gear(sDevRunCtrl.au8Level[u8CZ1]);

                // 闪烁三秒
                if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ1]) == 7)
                {
                    // 若指向当前炉头
                    if(sDevRunCtrl.u8CZIndex == u8CZ1)
                    {
                        // 炉头索引重回无效
                        sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
                    }
            
                    // 显示空闲
                    Display_Hob1Idle();
                    
                    // 关闭定时器
                    OS_TimerStop(&sDevRunCtrl.asLevelBlinkTimer[u8CZ1]);
                }
            }
            else
            {
                // 清除显示
                Display_Hob1Clear();
            }
        }
    break;
    case eHOB_IDLE_S2:
        
    break;
    case eHOB_RUNNING:
        // 闪烁档位
        if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ1])%2)
        {
            // 显示档位
            Display_Hob1Gear(sDevRunCtrl.au8Level[u8CZ1]);
        
            // 闪烁三秒
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ1]) == 7)
            {
                // 判断档位是否为零
                if(sDevRunCtrl.au8Level[u8CZ1] != 0)
                {
                    // 若所有炉头均未开启定时，则索引设置为无效
                    if(DevRun_CheckTimingEnable() == FALSE)
                    {
                        // 炉头索引重回无效
                        sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
                    }
                    
                    // 档位非零，继续运行
                    HobCtrl_StartHeating(u8CZ1);
                }
                else
                {
                    // 炉头索引重回无效
                    sDevRunCtrl.u8CZIndex = u8CZ_INVALID;

                    // 停止运行
                    HobCtrl_StopHeating(u8CZ1);
                }
            }
        }
        else
        {
            // 清除显示
            Display_Hob1Clear();
        }
    break;
    case eHOB_END:
        // 闪烁档位
        if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ1])%2)
        {
            // 显示档位
            Display_Hob1Gear(sDevRunCtrl.au8Level[u8CZ1]);
        
            // 闪烁2秒
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ1]) > 4)
            {
                //调试信息
                DEBUG("CZ1 back to S1\r\n");
                
                // 重回S1状态
                sDevRunCtrl.eRunState[u8CZ1] = eHOB_IDLE_S1;

                // 若指向当前炉头
                if(sDevRunCtrl.u8CZIndex == u8CZ1)
                {
                    // 炉头索引重回无效
                    sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
                }
            }
        }
        else
        {
            // 清除显示
            Display_Hob1Clear();
        }
    break;
    default:
    break;
    }
}

/*******************************************************************************
  * 函数名：DevRun_CZ2LevelBlinkHook
  * 功  能：设备运行-CZ2档位闪烁回调函数
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void DevRun_CZ2LevelBlinkHook(void)
{
    // 状态改变提前退出
    if(eDEV_RUN != Dev_GetCurrentState())
    {
        OS_TimerStop(&sDevRunCtrl.asLevelBlinkTimer[u8CZ2]);
        return;
    }

    // 根据当前状态，执行闪烁规则
    switch(sDevRunCtrl.eRunState[u8CZ2])
    {
    case eHOB_IDLE_S1:
        // 检查是否需要高温提醒
        if(YLComm_CoilTempGet(u8CZ2) > U8_COIL_OVERHEAT_TEMPER)
        {
            // 闪烁‘H’
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ2])%2)
            {
                // 显示'H'
                Display_Hob2Hot();

                // 信息调试
                DEBUG("CZ2 is hot\r\n");
            }
            else
            {
                // 清除显示
                Display_Hob2Clear();
            }
        }
        else
        {
            // 闪烁档位
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ2])%2)
            {
                // 显示档位
                Display_Hob2Gear(sDevRunCtrl.au8Level[u8CZ2]);

                // 闪烁三秒
                if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ2]) == 7)
                {
                    // 若指向当前炉头
                    if(sDevRunCtrl.u8CZIndex == u8CZ2)
                    {
                        // 炉头索引重回无效
                        sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
                    }
            
                    // 显示空闲
                    Display_Hob2Idle();
                    
                    // 关闭定时器
                    OS_TimerStop(&sDevRunCtrl.asLevelBlinkTimer[u8CZ2]);
                }
            }
            else
            {
                // 清除显示
                Display_Hob2Clear();
            }
        }
    break;
    case eHOB_IDLE_S2:
    break;
    case eHOB_RUNNING:
        // 闪烁档位
        if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ2])%2)
        {
            // 显示档位
            Display_Hob2Gear(sDevRunCtrl.au8Level[u8CZ2]);
        
            // 闪烁三秒
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ2]) == 7)
            {
                // 判断档位是否为零
                if(sDevRunCtrl.au8Level[u8CZ2] != 0)
                {
                    // 若所有炉头均未开启定时，则索引设置为无效
                    if(DevRun_CheckTimingEnable() == FALSE)
                    {
                        // 炉头索引重回无效
                        sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
                    }
                    
                    // 档位非零，继续运行
                    HobCtrl_StartHeating(u8CZ2);
                }
                else
                {
                    // 炉头索引重回无效
                    sDevRunCtrl.u8CZIndex = u8CZ_INVALID;

                    // 停止运行
                    HobCtrl_StopHeating(u8CZ2);
                }
            }
        }
        else
        {
            // 清除显示
            Display_Hob2Clear();
        }
    break;
    case eHOB_END:
        // 闪烁档位
        if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ2])%2)
        {
            // 显示档位
            Display_Hob2Gear(sDevRunCtrl.au8Level[u8CZ2]);
        
            // 闪烁2秒
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ2]) > 4)
            {
                //调试信息
                DEBUG("CZ2 back to S1\r\n");
                
                // 重回S1状态
                sDevRunCtrl.eRunState[u8CZ2] = eHOB_IDLE_S1;

                // 若指向当前炉头
                if(sDevRunCtrl.u8CZIndex == u8CZ2)
                {
                    // 炉头索引重回无效
                    sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
                }
            }
        }
        else
        {
            // 清除显示
            Display_Hob2Clear();
        }
    break;
    default:
    break;
    }
}

/*******************************************************************************
  * 函数名：DevRun_Hob3LevelBlinkHook
  * 功  能：设备运行-炉头3档位闪烁回调函数
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void DevRun_CZ3LevelBlinkHook(void)
{
    // 状态改变提前退出
    if(eDEV_RUN != Dev_GetCurrentState())
    {
        OS_TimerStop(&sDevRunCtrl.asLevelBlinkTimer[u8CZ3]);
        return;
    }

    // 根据当前状态，执行闪烁规则
    switch(sDevRunCtrl.eRunState[u8CZ3])
    {
    case eHOB_IDLE_S1:
        // 检查是否需要高温提醒
        if(YLComm_CoilTempGet(u8CZ3) > U8_COIL_OVERHEAT_TEMPER)
        {
            // 闪烁‘H’
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ3])%2)
            {
                // 显示'H'
                Display_Hob3Hot();

                // 信息调试
                DEBUG("CZ3 is hot\r\n");
            }
            else
            {
                // 清除显示
                Display_Hob3Clear();
            }
        }
        else
        {
            // 闪烁档位
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ3])%2)
            {
                // 显示档位
                Display_Hob3Gear(sDevRunCtrl.au8Level[u8CZ3]);

                // 闪烁三秒
                if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ3]) == 7)
                {
                    // 若指向当前炉头
                    if(sDevRunCtrl.u8CZIndex == u8CZ3)
                    {
                        // 炉头索引重回无效
                        sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
                    }
            
                    // 显示空闲
                    Display_Hob3Idle();
                    
                    // 关闭定时器
                    OS_TimerStop(&sDevRunCtrl.asLevelBlinkTimer[u8CZ3]);
                }
            }
            else
            {
                // 清除显示
                Display_Hob3Clear();
            }
        }
    break;
    case eHOB_IDLE_S2:
    break;
    case eHOB_RUNNING:
        // 闪烁档位
        if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ3])%2)
        {
            // 显示档位
            Display_Hob3Gear(sDevRunCtrl.au8Level[u8CZ3]);
        
            // 闪烁三秒
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ3]) == 7)
            {
                // 判断档位是否为零
                if(sDevRunCtrl.au8Level[u8CZ3] != 0)
                {
                    // 若所有炉头均未开启定时，则索引设置为无效
                    if(DevRun_CheckTimingEnable() == FALSE)
                    {
                        // 炉头索引重回无效
                        sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
                    }
                    
                    // 档位非零，继续运行
                    HobCtrl_StartHeating(u8CZ3);
                }
                else
                {
                    // 炉头索引重回无效
                    sDevRunCtrl.u8CZIndex = u8CZ_INVALID;

                    // 停止运行
                    HobCtrl_StopHeating(u8CZ3);
                }
            }
        }
        else
        {
            // 清除显示
            Display_Hob3Clear();
        }
    break;
    case eHOB_END:
        // 闪烁档位
        if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ3])%2)
        {
            // 显示档位
            Display_Hob3Gear(sDevRunCtrl.au8Level[u8CZ3]);
        
            // 闪烁2秒
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ3]) > 4)
            {
                //调试信息
                DEBUG("CZ3 back to S1\r\n");
                
                // 重回S1状态
                sDevRunCtrl.eRunState[u8CZ3] = eHOB_IDLE_S1;

                // 若指向当前炉头
                if(sDevRunCtrl.u8CZIndex == u8CZ3)
                {
                    // 炉头索引重回无效
                    sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
                }
            }
        }
        else
        {
            // 清除显示
            Display_Hob3Clear();
        }
    break;
    default:
    break;
    }
}

/*******************************************************************************
  * 函数名：DevRun_Hob4LevelBlinkHook
  * 功  能：设备运行-炉头4档位闪烁回调函数
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void DevRun_CZ4LevelBlinkHook(void)
{
    // 状态改变提前退出
    if(eDEV_RUN != Dev_GetCurrentState())
    {
        OS_TimerStop(&sDevRunCtrl.asLevelBlinkTimer[u8CZ4]);
        return;
    }

    // 根据当前状态，执行闪烁规则
    switch(sDevRunCtrl.eRunState[u8CZ4])
    {
    case eHOB_IDLE_S1:
        // 检查是否需要高温提醒
        if(YLComm_CoilTempGet(u8CZ4) > U8_COIL_OVERHEAT_TEMPER)
        {
            // 闪烁‘H’
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ4])%2)
            {
                // 显示'H'
                Display_Hob4Hot();

                // 信息调试
                DEBUG("CZ4 is hot\r\n");
            }
            else
            {
                // 清除显示
                Display_Hob4Clear();
            }
        }
        else
        {
            // 闪烁档位
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ4])%2)
            {
                // 显示档位
                Display_Hob4Gear(sDevRunCtrl.au8Level[u8CZ4]);

                // 闪烁三秒
                if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ4]) == 7)
                {
                    // 若指向当前炉头
                    if(sDevRunCtrl.u8CZIndex == u8CZ4)
                    {
                        // 炉头索引重回无效
                        sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
                    }
            
                    // 显示空闲
                    Display_Hob4Idle();
                    
                    // 关闭定时器
                    OS_TimerStop(&sDevRunCtrl.asLevelBlinkTimer[u8CZ4]);
                }
            }
            else
            {
                // 清除显示
                Display_Hob4Clear();
            }
        }
    break;
    case eHOB_IDLE_S2:
    break;
    case eHOB_RUNNING:
        // 闪烁档位
        if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ4])%2)
        {
            // 显示档位
            Display_Hob4Gear(sDevRunCtrl.au8Level[u8CZ4]);
        
            // 闪烁三秒
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ4]) == 7)
            {
                // 判断档位是否为零
                if(sDevRunCtrl.au8Level[u8CZ4] != 0)
                {
                    // 若所有炉头均未开启定时，则索引设置为无效
                    if(DevRun_CheckTimingEnable() == FALSE)
                    {
                        // 炉头索引重回无效
                        sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
                    }
                    
                    // 档位非零，继续运行
                    HobCtrl_StartHeating(u8CZ4);
                }
                else
                {
                    // 炉头索引重回无效
                    sDevRunCtrl.u8CZIndex = u8CZ_INVALID;

                    // 停止运行
                    HobCtrl_StopHeating(u8CZ4);
                }
            }
        }
        else
        {
            // 清除显示
            Display_Hob4Clear();
        }
    break;
    case eHOB_END:
        // 闪烁档位
        if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ4])%2)
        {
            // 显示档位
            Display_Hob4Gear(sDevRunCtrl.au8Level[u8CZ4]);
        
            // 闪烁2秒
            if(OS_TimerGetExpiredTimes(&sDevRunCtrl.asLevelBlinkTimer[u8CZ4]) > 4)
            {
                //调试信息
                DEBUG("CZ4 back to S1\r\n");
                
                // 重回S1状态
                sDevRunCtrl.eRunState[u8CZ4] = eHOB_IDLE_S1;

                // 若指向当前炉头
                if(sDevRunCtrl.u8CZIndex == u8CZ4)
                {
                    // 炉头索引重回无效
                    sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
                }
            }
        }
        else
        {
            // 清除显示
            Display_Hob4Clear();
        }
    break;
    default:
    break;
    }
}

/*******************************************************************************
  * 函数名：DevRun_BoostPressHandler
  * 功  能：设备运行-Boost键处理函数
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void DevRun_BoostPressHandler(void)
{
    // 检查当前是否选择炉头
    if(sDevRunCtrl.u8CZIndex == u8CZ_INVALID)
    {
        // 未选择炉头，提前退出
        return;
    }

}

/*******************************************************************************
  * 函数名：DevRun_FullZonePressHandler
  * 功  能：设备运行-FullZone键处理函数 
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void DevRun_FullZonePressHandler(void)
{

}

/*******************************************************************************
  * 函数名：DevRun_AddPressHandler
  * 功  能：设备运行-KeepWarm键处理函数
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void DevRun_KeepWarmPressHandler(void)
{
    // 检查当前是否选择炉头
    if(sDevRunCtrl.u8CZIndex == u8CZ_INVALID)
    {
        // 未选择炉头，提前退出
        return;
    }
}

/*******************************************************************************
  * 函数名：DevRun_PausePressHandler
  * 功  能：设备运行-Pause键处理函数
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void DevRun_PausePressHandler(void)
{

}

/*******************************************************************************
  * 函数名：DevRun_AddPressHandler
  * 功  能：设备运行-加键短按处理
  * 参  数：Bool bBuzzer：蜂鸣器开/关
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void DevRun_AddPressHandler(Bool bBuzzer)
{
    // 暂停时不允许操作按键
    if(sDevRunCtrl.bPauseFlag == TRUE)
    {
        return;
    }

    // 选中炉头，且炉头在运行时，才能调节时间
    if(sDevRunCtrl.u8CZIndex <= u8CZ4 && sDevRunCtrl.eRunState[sDevRunCtrl.u8CZIndex] == eHOB_RUNNING)
    {
        // 设备运行中时，定时器作为烹饪定时
        sDevRunCtrl.eTimingType = eTIMING_COOK_TIMER;
        
        // 分钟自加
        sDevRunCtrl.au8TimingTime[sDevRunCtrl.u8CZIndex]++;
        
        // 最大定时99分钟
        if(sDevRunCtrl.au8TimingTime[sDevRunCtrl.u8CZIndex] > 99)
        {
            sDevRunCtrl.au8TimingTime[sDevRunCtrl.u8CZIndex] = 0;
        }
        
        // 使能定时使能标志位
        sDevRunCtrl.bTimerEnable[sDevRunCtrl.u8CZIndex] = TRUE;
        
        // 更新秒
        sDevRunCtrl.au16TimingTimeS[sDevRunCtrl.u8CZIndex] = sDevRunCtrl.au8TimingTime[sDevRunCtrl.u8CZIndex]*60;

        // 显示时间
        Display_ShowTime(sDevRunCtrl.au8TimingTime[sDevRunCtrl.u8CZIndex]);

        // 点亮开启定时CZ的Dot，关闭未开定时的Dot
        for(U8 u8CZIndex = u8CZ1;u8CZIndex <= u8CZ4;u8CZIndex++)
        {
            if(sDevRunCtrl.bTimerEnable[u8CZIndex] == TRUE)
            {
                Display_HobDot(u8CZIndex,ON);
            }
            else
            {
                Display_HobDot(u8CZIndex,OFF);
            }
        }

        // 重启时间闪烁定时器
        OS_TimerRestart(&sDevRunCtrl.sTimeBlinkTimer,500,DevRun_TimingTimeBlinkHook);

        if(bBuzzer)
        {
            // 按键音
            Buzzer_Play(eBUZZER_SOUND_KEY_PRESS,eBUZZER_VOL_HIGH);
        }
    }
}

/*******************************************************************************
  * 函数名：DevRun_SubPressHandler
  * 功  能：设备运行-减键短按处理
  * 参  数：Bool bBuzzer：蜂鸣器开/关
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void DevRun_SubPressHandler(Bool bBuzzer)
{
    // 暂停时不允许操作按键
    if(sDevRunCtrl.bPauseFlag == TRUE)
    {
        return;
    }

    // 选中炉头，且炉头在运行时，才能调节时间
    if(sDevRunCtrl.u8CZIndex <= u8CZ4 && sDevRunCtrl.eRunState[sDevRunCtrl.u8CZIndex] == eHOB_RUNNING)
    {
        // 设备运行中时，定时器作为烹饪定时
        sDevRunCtrl.eTimingType = eTIMING_COOK_TIMER;
        
        // 分钟自减
        sDevRunCtrl.au8TimingTime[sDevRunCtrl.u8CZIndex]--;
        
        // 最小时间为0
        if((S8)sDevRunCtrl.au8TimingTime[sDevRunCtrl.u8CZIndex] <= 0)
        {
            // 置零定时时间
            sDevRunCtrl.au8TimingTime[sDevRunCtrl.u8CZIndex] = 0;

            // 清除定时使能标志位
            sDevRunCtrl.bTimerEnable[sDevRunCtrl.u8CZIndex] = FALSE;

            // 清空秒
            sDevRunCtrl.au16TimingTimeS[sDevRunCtrl.u8CZIndex] = 0;

            // 点亮开启定时CZ的Dot，关闭未开定时的Dot
            for(U8 u8CZIndex = u8CZ1;u8CZIndex <= u8CZ4;u8CZIndex++)
            {
                if(sDevRunCtrl.bTimerEnable[u8CZIndex] == TRUE)
                {
                    Display_HobDot(u8CZIndex,ON);
                }
                else
                {
                    Display_HobDot(u8CZIndex,OFF);
                }
            }
        }
        else
        {
            // 使能定时使能标志位
            sDevRunCtrl.bTimerEnable[sDevRunCtrl.u8CZIndex] = TRUE;
            
            // 更新秒
            sDevRunCtrl.au16TimingTimeS[sDevRunCtrl.u8CZIndex] = sDevRunCtrl.au8TimingTime[sDevRunCtrl.u8CZIndex]*60;

            // 点亮开启定时CZ的Dot，关闭未开定时的Dot
            for(U8 u8CZIndex = u8CZ1;u8CZIndex <= u8CZ4;u8CZIndex++)
            {
                if(sDevRunCtrl.bTimerEnable[u8CZIndex] == TRUE)
                {
                    Display_HobDot(u8CZIndex,ON);
                }
                else
                {
                    Display_HobDot(u8CZIndex,OFF);
                }
            }
        }
        
        // 显示时间
        Display_ShowTime(sDevRunCtrl.au8TimingTime[sDevRunCtrl.u8CZIndex]);
        
        // 重启时间闪烁定时器
        OS_TimerRestart(&sDevRunCtrl.sTimeBlinkTimer,500,DevRun_TimingTimeBlinkHook);

        if(bBuzzer)
        {
            // 按键音
            Buzzer_Play(eBUZZER_SOUND_KEY_PRESS,eBUZZER_VOL_HIGH);
        }
    }

}

/*******************************************************************************
  * 函数名：DevRun_SliderHandler
  * 功  能：设备运行-滑条处理函数
  * 参  数：U8 u8Slider：滑条值
  * 返回值：用于处理滑条档位
  * 说  明：滑条逻辑处理
*******************************************************************************/
void DevRun_SliderHandler(U8 u8Slider)
{
    // 是否闪烁档位标志位
    Bool bLevelFlash = TRUE;
    
    // 检查当前是否选择炉头
    if(sDevRunCtrl.u8CZIndex == u8CZ_INVALID)
    {
        // 未选择炉头，提前退出
        return;
    }

    // 根据当前状态，执行不同操作
    switch(sDevRunCtrl.eRunState[sDevRunCtrl.u8CZIndex])
    {
    case eHOB_IDLE_S1:
        // 更新状态
        sDevRunCtrl.eRunState[sDevRunCtrl.u8CZIndex] = eHOB_RUNNING;
        // 更新档位
        sDevRunCtrl.au8Level[sDevRunCtrl.u8CZIndex] = u8Slider;
        // 提示音
        Buzzer_Play(eBUZZER_SOUND_SLIDER_PRESS,eBUZZER_VOL_HIGH);
    break;
    case eHOB_IDLE_S2:
        // 不需要闪烁档位
        bLevelFlash = FALSE;
        // 此时炉头无锅，禁止修改档位
        Buzzer_Play(eBUZZER_SOUND_ACTION_NOT_ALLOWED,eBUZZER_VOL_HIGH);
    break;
    case eHOB_RUNNING:
        // 更新档位
        sDevRunCtrl.au8Level[sDevRunCtrl.u8CZIndex] = u8Slider;

        // 检查当前炉头是否启动定时
        if(sDevRunCtrl.bTimerEnable[sDevRunCtrl.u8CZIndex])
        {
            // 显示剩余时间
            Display_ShowTime(sDevRunCtrl.au8TimingTime[sDevRunCtrl.u8CZIndex]);

            // 显示Dot
            Display_HobDot(sDevRunCtrl.u8CZIndex,ON);
        }
        else
        {
            // 显示--
            Display_ShowIdle();

            // 熄灭Dot
            Display_HobDot(sDevRunCtrl.u8CZIndex,OFF);
        }

        // 重启定时显示定时器
        OS_TimerReset(&sDevRunCtrl.sTimeBlinkTimer);
        
        // 提示音
        Buzzer_Play(eBUZZER_SOUND_SLIDER_PRESS,eBUZZER_VOL_HIGH);
    break;
    default:
    break;
    }

    if(bLevelFlash == TRUE)
    {
        // 根据当前选中炉头，启动档位显示定时器
        switch(sDevRunCtrl.u8CZIndex)
        {
        case u8CZ1:
            // 显示档位
            Display_Hob1Gear(sDevRunCtrl.au8Level[u8CZ1]);
            // 重启定时器
            OS_TimerRestart(&sDevRunCtrl.asLevelBlinkTimer[u8CZ1],500,DevRun_CZ1LevelBlinkHook);
        break;
        case u8CZ2:
            // 显示档位
            Display_Hob2Gear(sDevRunCtrl.au8Level[u8CZ2]);
            // 重启定时器
            OS_TimerRestart(&sDevRunCtrl.asLevelBlinkTimer[u8CZ2],500,DevRun_CZ2LevelBlinkHook);
        break;
        case u8CZ3:
            // 显示档位
            Display_Hob3Gear(sDevRunCtrl.au8Level[u8CZ3]);
            // 重启定时器
            OS_TimerRestart(&sDevRunCtrl.asLevelBlinkTimer[u8CZ3],500,DevRun_CZ3LevelBlinkHook);
        break;
        case u8CZ4:
            // 显示档位
            Display_Hob4Gear(sDevRunCtrl.au8Level[u8CZ4]);
            // 重启定时器
            OS_TimerRestart(&sDevRunCtrl.asLevelBlinkTimer[u8CZ4],500,DevRun_CZ4LevelBlinkHook);
        break;
        default:
        break;
        }
    }
}

/*******************************************************************************
  * 函数名：DevRum_S1LongPressHandler
  * 功  能：设备运行-S1键长按处理函数
  * 参  数：U8 u8CZIndex：炉头编号
  * 返回值：无
  * 说  明：长按S1关闭当前运行的炉头
*******************************************************************************/
void DevRum_S1LongPressHandler(void)
{
    if(sDevRunCtrl.u8CZIndex <= u8CZ4)
    {
        // 停止运行
        HobCtrl_StopHeating(sDevRunCtrl.u8CZIndex);

        // 炉头索引重回无效
        sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
    }
}

/*******************************************************************************
  * 函数名：DevRun_HobPressHandler
  * 功  能：设备运行-炉头按键处理函数
  * 参  数：U8 u8CZIndex：炉头编号
  * 返回值：无
  * 说  明：选中炉头
*******************************************************************************/
void DevRun_HobPressHandler(U8 u8CZIndex)
{
    // 设备处于暂停状态，滑条不使能
    if(sDevRunCtrl.bPauseFlag == TRUE)
    {
        // 提前退出
        return;
    }

    // 根据当前状态，执行不同操作
    if(sDevRunCtrl.eRunState[u8CZIndex] == eHOB_IDLE_S2)
    {
        // 此时在闪烁无锅
        DEBUG("CZ%d no pan, can not set level\r\n",u8CZIndex+1);

        // 无效音
        Buzzer_Play(eBUZZER_SOUND_ACTION_NOT_ALLOWED,eBUZZER_VOL_HIGH);
        
        // 显示无锅符号
        switch(u8CZIndex)
        {
        case u8CZ1:
            Display_Hob1NoPot();
        break;
        case u8CZ2:
            Display_Hob2NoPot();
        break;
        case u8CZ3:
            Display_Hob3NoPot();
        break;
        case u8CZ4:
            Display_Hob4NoPot();
        break;
        }   
    }
    else
    {
        // 信息调试
        DEBUG("Select %d cz\r\n",u8CZIndex+1);
    
        // 更新炉头索引
        sDevRunCtrl.u8CZIndex = u8CZIndex;
        
        // 检查当前炉头是否启动定时
        if(sDevRunCtrl.bTimerEnable[sDevRunCtrl.u8CZIndex])
        {
            // 显示剩余时间
            Display_ShowTime(sDevRunCtrl.au8TimingTime[sDevRunCtrl.u8CZIndex]);
            
            // 显示Dot
            Display_HobDot(sDevRunCtrl.u8CZIndex,ON);
        }
        else
        {
            // 显示--
            Display_ShowIdle();
            
            // 熄灭Dot
            Display_HobDot(sDevRunCtrl.u8CZIndex,OFF);
        }
        
        // 按键音
        Buzzer_Play(eBUZZER_SOUND_KEY_PRESS,eBUZZER_VOL_HIGH);
        
        // 重启定时显示定时器
        OS_TimerReset(&sDevRunCtrl.sTimeBlinkTimer);
        
        // 根据所选炉头，启动档位闪烁定时器
        switch(sDevRunCtrl.u8CZIndex)
        {
        case u8CZ1:
            Display_Hob1Gear(sDevRunCtrl.au8Level[sDevRunCtrl.u8CZIndex]);
            OS_TimerRestart(&sDevRunCtrl.asLevelBlinkTimer[u8CZ1],500,DevRun_CZ1LevelBlinkHook);
        break;
        case u8CZ2:
            Display_Hob2Gear(sDevRunCtrl.au8Level[sDevRunCtrl.u8CZIndex]);
            OS_TimerRestart(&sDevRunCtrl.asLevelBlinkTimer[u8CZ2],500,DevRun_CZ2LevelBlinkHook);
        break;
        case u8CZ3:
            Display_Hob3Gear(sDevRunCtrl.au8Level[sDevRunCtrl.u8CZIndex]);
            OS_TimerRestart(&sDevRunCtrl.asLevelBlinkTimer[u8CZ3],500,DevRun_CZ3LevelBlinkHook);
        break;
        case u8CZ4:
            Display_Hob4Gear(sDevRunCtrl.au8Level[sDevRunCtrl.u8CZIndex]);
            OS_TimerRestart(&sDevRunCtrl.asLevelBlinkTimer[u8CZ4],500,DevRun_CZ4LevelBlinkHook);
        break;
        default:
        break;
        }
    }
}

/*******************************************************************************
  * 函数名：DevRun_HobPressHandler
  * 功  能：设备运行-炉头按键处理函数
  * 参  数：U8 u8CZIndex：炉头编号
  * 返回值：无
  * 说  明：选中炉头
*******************************************************************************/
void DevRun_HobLongPressHandler(U8 u8CZIndex)             // 设备运行-炉头按键处理函数
{
    // 停止运行
    HobCtrl_StopHeating(u8CZIndex);

    // 炉头索引重回无效
    sDevRunCtrl.u8CZIndex = u8CZ_INVALID;
}

/*******************************************************************************
  * 函数名：DevRun_GetCZIndex
  * 功  能：设备运行-获取CZ的索引
  * 参  数：无
  * 返回值：
  * 说  明：获取当前指向的炉头索引
*******************************************************************************/
U8 DevRun_GetCZIndex(void)
{
    return sDevRunCtrl.u8CZIndex;
}

/*******************************************************************************
  * 函数名：DevRun_CheckFullZone
  * 功  能：设备运行-检查fullzone是否使能
  * 参  数：无
  * 返回值：U8 CZ数量
  * 说  明：无
*******************************************************************************/
Bool DevRun_CheckFullZone(void)
{
    return sDevRunCtrl.bFullZoneEnable;
}


/*******************************************************************************
  * 函数名：DevRun_CheckTimingEnable
  * 功  能：设备运行-检查是否有CZ使能定时
  * 参  数：无
  * 返回值：有无炉头正在定时
  * 说  明：任意炉头使能定时，则返回TRUE. 所有炉头不开启定时，则返回FALSE
*******************************************************************************/
Bool DevRun_CheckTimingEnable(void)
{
    if(sDevRunCtrl.bTimerEnable[u8CZ1] == FALSE && sDevRunCtrl.bTimerEnable[u8CZ2] == FALSE
        && sDevRunCtrl.bTimerEnable[u8CZ3] == FALSE && sDevRunCtrl.bTimerEnable[u8CZ4] == FALSE)
    {
        return FALSE;
    }
    else
    {
        return TRUE;
    }
}

/*******************************************************************************
  * 函数名：DevRun_CheckIsBusy
  * 功  能：设备运行-检查设备是否正忙
  * 参  数：无
  * 返回值：TURE:设备正在运行  FALSE:设备空闲
  * 说  明：无
*******************************************************************************/
Bool DevRun_CheckIsBusy(void)
{
    Bool bRet = FALSE;

    // 至少有一个CookingZone处于运行或暂停状态时，认为设备正忙
    if(sDevRunCtrl.eRunState[0] == eHOB_RUNNING || sDevRunCtrl.eRunState[0] == eHOB_PAUSE
        || sDevRunCtrl.eRunState[1] == eHOB_RUNNING || sDevRunCtrl.eRunState[1] == eHOB_PAUSE
        || sDevRunCtrl.eRunState[2] == eHOB_RUNNING || sDevRunCtrl.eRunState[2] == eHOB_PAUSE
        || sDevRunCtrl.eRunState[3] == eHOB_RUNNING || sDevRunCtrl.eRunState[3] == eHOB_PAUSE)
    {
        bRet = TRUE;
    }

    return bRet;
}


/*******************************************************************************
  * 函数名：DevRun_Init
  * 功  能：设备运行-初始化
  * 参  数：无
  * 返回值：无
  * 说  明：该函数仅在设备开机后运行一次
*******************************************************************************/
void DevRun_Init(void)
{
    // 清零控制信息
    memset(&sDevRunCtrl,0x00,sizeof(sDevRunCtrl));

    // 炉头索引指向无效
    sDevRunCtrl.u8CZIndex = u8CZ_INVALID;

    // 炉头状态初始化，默认开机为S1状态
    sDevRunCtrl.eRunState[u8CZ1] = eHOB_IDLE_S1;
    sDevRunCtrl.eRunState[u8CZ2] = eHOB_IDLE_S1;
    sDevRunCtrl.eRunState[u8CZ3] = eHOB_IDLE_S1;
    sDevRunCtrl.eRunState[u8CZ4] = eHOB_IDLE_S1;

    // 开机欢迎音
    Buzzer_Play(eBUZZER_SOUND_WELCOM,eBUZZER_VOL_HIGH);
    
    // 开启继电器
    Relay_Update(ON);
    
    // 复位空闲检测
    DevStandby_ResetIdleCheck();
    
    // 四个炉头均显示'-'
    Display_Hob1Idle();
    Display_Hob2Idle();
    Display_Hob3Idle();
    Display_Hob4Idle();

    // 检查童锁状态
    if(Dev_GetChildLock() == TRUE)
    {
        // 显示Lo
        Display_ShowLock();
    }
    else
    {
        // 时间显示“--” 
        Display_ShowIdle();
    }
}

/***************************** 文件结束 ***************************************/

